# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__="MrEction"
__date__ ="$Feb 8, 2011 11:38:20 AM$"
# To change this template, choose Tools | Templates
# and open the template in the editor.

__author__="MrEction"
__date__ ="$Jan 27, 2011 4:12:10 PM$"


import pygame
from pygame.draw import *
from hexconfig import *
import random

import pickle

HEXSIDELEN = 24
BOARDSIZE = 4
GRIDORIGIN = (400.0,300.0)
HEXORIGIN = (GRIDORIGIN[0]-dx(HEXSIDELEN,math.radians(60.0))/2,\
            GRIDORIGIN[1]-dy(HEXSIDELEN,math.radians(60.0))/2)
LINETHICK = 2

GRIDXLEN = 10
GRIDYLEN = 10
GRIDZLEN = 10


DEBUGCIRCLELOCS = False

BOARDCOLOR = (245,245,245)
BGFILENAME = "reapertotalwskulls.png"
"""
              ____
          /    \\
     ____/ 0 1-1\\____
         \      //    \
   -1 1 0 \____// 1 0-1\___
          /    \\      /
     ____/ 0 0 0\\____/ 2 -1 -1
         \      //    \
   -1 0 1 \____// 1-1 0\__
          /    \\      /
     ____/ 0-1 1\\____/
         \      //    \
          \____//      \

    the flower down is recursively adding the the bottom,
    until any values hit extremes

    """
#THIS IS A LIST OF EM STARTING TOP FIRST AND GOING CC
HEXDIRECTIONS = [(0,1,-1),(-1,1,0),(-1,0,1),(0,-1,1),(1,-1,0),(1,0,-1)]
UP = 0

IDLE = 0
ACTIVE = 1
GAMEOVER = 2

SINGLE_SELECT = 0
PUSH_SELECT = 1
KING_SELECT = 2


def locEq(loc1,loc2):
    if loc1==None or loc2==None:
        return False
    flag = True
    for i in range(3):
        if not loc1[i] == loc2[i]:
            flag = False
            break
    return flag


def getPosFromHexLoc(hexLoc,drawable = False):
    pos = [HEXORIGIN[0],HEXORIGIN[1]]
    l = HEXSIDELEN


    #X COMPONENT
    pos[0]+=l*hexLoc[0]
    #YCOMPONENT
    pos[0]+=dx(l*hexLoc[1],math.radians(-120.0))
    pos[1]+=dy(l*hexLoc[1],math.radians(-120.0))
    #ZCOMPONENT
    pos[0]+=dx(l*hexLoc[2],math.radians(120.0))
    pos[1]+=dy(l*hexLoc[2],math.radians(120.0))

    if drawable:
        pos = [int(pos[0]),int(pos[1])]
    return pos

def getGridLocFromMouse(mouseloc):
   # /* doubles x, y, and z hold the initial raw ungridded position */

  x,y = mouseloc
  z = 0
  ix = int(x)
  iy = int(y)
  iz = int(z)
  rx = int(x)
  ry = int(y)
  rz = int(z)

  s = ix+iy+iz

  if s :
    abs_dx = math.fabs(rx-x),
    abs_dy = math.fabs(ry-y)
    abs_dz = math.fabs(rz-z);

    if abs_dx >= abs_dy and abs_dx >= abs_dz:
        ix -= s; # abs_dx is max.
    elif abs_dy >= abs_dx and abs_dy >= abs_dz:
      iy -= s; #/* abs_dy is max. *.
    else: iz-=s;

  print "get gridloc: ",(ix,iy,iz)
  return (ix,iy,iz)

  #/* ix, iy, iz now hold the coordinates of the hex. */




class LocLerper():
    def __init__(self,unit,endloc,time):
        self.startloc = getPosFromHexLoc(unit.hexloc,True)
        self.endloc = getPosFromHexLoc(endloc,True)
        self.rangeSize = [self.endloc[0]-self.startloc[0],self.endloc[1]-self.startloc[1]]
        self.timec = 0
        self.endtime = time
        self.endHex = endloc
        self.finished = False
        self.unit = unit
        self.unit.drawLerpMode = True

    def update(self,etime):
        self.timec +=etime
        if self.timec>self.endtime:
            self.timec = self.endtime
            self.unit.hexloc = self.endHex
            self.finished = True
            self.unit.drawLerpMode = False
        n = self.timec/self.endtime
        self.unit.drawLoc = [self.startloc[0]+self.rangeSize[0]*n,self.startloc[1]+self.rangeSize[1]*n]


class Hexnake():
    def __init__(self):
        self.body = []
        self.length = []
        self.direction = UP

    def update(self,etime):
        return

    def draw(self,surf):
        for b in self.body:
            pass
IDLE = 0
PATROLLING = 1

class Unit():
    def __init__(self,team = 0):
        self.hexloc = [0,0,0]
        self.team = team
        self.state = IDLE
        self.drawLerpMode = False
        self.drawLoc = [0.0,0.0]
        self.dead = False
        self.king = False
    def update(self,etime):
        #self.rotateView()
        #self.checkPlayerVisibility()
        if self.state == IDLE:
            return

        print "DOING CRAZY SHIT, just lerping when commanded"
        return

    def draw(self,surf):
        if not self.drawLerpMode:
            drawLoc = getPosFromHexLoc(self.hexloc,True)
        else:
            drawLoc = self.drawLoc

        circle(surf,(0,0,0),drawLoc,16)
        
        if self.team == 0:
            circle(surf,P0UNITCOLOR,drawLoc,12)
        else:
            circle(surf,P1UNITCOLOR,drawLoc,12)

    def drawDead(self,surf,drawLoc):
        circle(surf,(0,0,0),drawLoc,16)

        if self.team == 0:
            circle(surf,P0UNITCOLOR,drawLoc,12)
        else:
            circle(surf,P1UNITCOLOR,drawLoc,12)



class King(Unit):
    def __init__(self,team = 0):
        Unit.__init__(self,team)
        self.crown = pygame.image.load("Crown.png")
        self.crown.set_colorkey((255,255,255))
        self.king = True
        
    def draw(self,surf):
        Unit.draw(self,surf)
        drawRect =self.crown.get_rect(center = getPosFromHexLoc(self.hexloc,True))
        #drawRect.top-=4

        if not self.drawLerpMode:
            surf.blit(self.crown,drawRect.topleft)
        else:
            surf.blit(self.crown,self.crown.get_rect(center = self.drawLoc))

class HexWorld():
    
    def __init__(self):
        self.scores = [0,0]
        self.setup()

    def setup(self):

        pygame.init()
        #print SWIDTH,",",SHEIGHT
        self.screen = pygame.display.set_mode((SWIDTH,SHEIGHT))#,pygame.HWSURFACE)
        pygame.display.set_caption("HEXworld")


        pygame.event.set_grab(False)
        self.clock = pygame.time.Clock()
        #pygame.font.initialize()

        self.keyPressDict = {}
        for k in KEYLIST:
            self.keyPressDict[k] = False
        self.debugMode = False


        self.mouseHold = False

        self.state = IDLE

        self.gridSetup()

        #self.discoFlag STUFF
        self.gridanimtick  = 0.0
        self.animGridList = []
        self.animspd = 100
        self.discoFlag = False
        #self.discoFlag STUFF

        self.actionCounter = 0
        self.zoneList =[]

        self.boardElements = {}
        self.boardSetup()
        self.drawBoardElements = True

        self.bg = pygame.image.load(BGFILENAME)
        #pygame.font.initialize()
        #self.font = pygame.font.Font(None,12)
        self.turnFont = pygame.font.Font("./Living Hell.ttf",48)

        gameOverFont = pygame.font.Font("./Living Hell.ttf",72)
        self.p1WinRen = gameOverFont.render("PLAYER 1 WINS",1,(240,215,0))
        self.p1WinRen.blit(gameOverFont.render("PLAYER 1 WINS",1,(240,0,0)),(-2,-2))
        self.p2WinRen = gameOverFont.render("PLAYER 2 WINS",1,(0,215,240))
        self.p2WinRen.blit(gameOverFont.render("PLAYER 2 WINS",1,(0,0,240)),(-2,-2))
        self.activePlayer = 0


        self.moveRens = []
        self.pushRens = []
        self.throwRens = []
        self.warpRens = []
        self.kingMoveRens = []

        actionFont = pygame.font.Font("./Shoguns Clan.ttf",48)

        for i in range(2):
            bcol = (253,199,23) if i == 0 else (2,232,230)
            fcol = (210,0,0) if i == 0 else (0,0,210)

            self.moveRens.append( actionFont.render("MOVE",1,bcol) )
            self.moveRens[i].blit(actionFont.render("MOVE",1,fcol),(-2,-2))
            self.pushRens.append( actionFont.render("PUSH",1,bcol))
            self.pushRens[i].blit(actionFont.render("PUSH",1,fcol),(-2,-2))
            self.throwRens.append( actionFont.render("THROW!",1,bcol))
            self.throwRens[i].blit(actionFont.render("THROW!",1,fcol),(-2,-2))

            self.warpRens.append( actionFont.render("WARP!",1,bcol) )
            self.warpRens[i].blit(actionFont.render("WARP!",1,fcol),(-2,-2))

            self.kingMoveRens.append( actionFont.render("KING MOVE",1,bcol) )
            self.kingMoveRens[i].blit(actionFont.render("KING MOVE",1,fcol),(-2,-2))


        self.state = IDLE
        

        self.locLerps = []

        self.crown = self.p0king.crown
        self.winner = -1

        self.selectMode = None

        self.warps = self.boardElements["warp"][0]

        self.scanAll()
        
    def boardSetup(self):
        elements = [["border",BORDERCOLOR],["death",DEATHCOLOR],["warp",WARPCOLOR],\
                ["p0king",KINGSPOTCOLOR],["p1king",KINGSPOTCOLOR]]
        #self.boardElements["border"]= self.loadZone("border")
        for e in elements:
            self.boardElements[e[0]] = [self.loadZone(e[0]),e[1]]

        self.setupUnits(self.loadZone("p0defaultstart"),self.loadZone("p1defaultstart"))
        
    def setupUnits(self,setup0zone,setup1zone):
        self.p0units = []
        self.p1units = []

        for i in range(8):
            unit = Unit(0)
            unit.hexloc = setup0zone[i]
            self.p0units.append(unit)
            unit = Unit(1)
            unit.hexloc = setup1zone[i]
            self.p1units.append(unit)

        king = King(0)
        king.hexloc = self.loadZone("p0king")[0]
        self.p0king = king
        king = King(1)
        king.hexloc = self.loadZone("p1king")[0]
        self.p1king = king
        self.selectedUnit = None
        self.actionHighlight = []
        self.walkSpaces = []


        

        self.movedThisTurn = False
        self.moveDraw = False
        self.pushedThisTurn = False
        self.thrownThisTurn = False
        self.warpedThisTurn = False  #i think logically this is not used because the turn would have to end
                                    #could be a variable that is kept around for that specific case

        self.kingMovedThisTurn = False


        self.pushableNbrs = []
        self.pushSelection = None
        self.pushSpace = []

        self.movedUnits = []  #used to store the involved movement units it a push or a move happens


        self.throwableUnits = []
        self.thrownUnit = None
        self.throwSpaces = []


        self.warpableUnits = []
        self.warpSpaces = []

        
    def gridSetup(self):
        self.gridLocs = []
        """
        for x in range(GRIDXLEN):
            self.gridLocs.append([])
            for y in range(GRIDYLEN):
                self.gridLocs[x].append([])
                for z in range(GRIDZLEN):

                    loc = 0
                    self.gridLocs[x][y].append(loc)
        """
        self.gridLocs = self.getFlowerOutGrid()


    def checkUnitClick(self,screenLoc,checkAll = False):
        if not checkAll:
            searchlist = self.p0units if self.activePlayer == 0 else self.p1units
        else:
            searchlist = []
            searchlist.extend(self.p0units)
            searchlist.extend(self.p1units)
            
        for unit in searchlist:
            if dist(getPosFromHexLoc(unit.hexloc, False),screenLoc) < HEXSIDELEN:
                
                return unit

    def checkKingClick(self,screenLoc):

        searchlist = []
        searchlist.append(self.p0king if self.activePlayer == 0 else self.p1king)
            #searchlist.extend(self.p1units)

        for unit in searchlist:
            if dist(getPosFromHexLoc(unit.hexloc, False),screenLoc) < HEXSIDELEN:
                return unit

    def getPushableSpaces(self,unit,nbr):
        if unit == None or nbr == None:
            return []

        dirs = [(nbr.hexloc[0] - unit.hexloc[0],nbr.hexloc[1]-unit.hexloc[1],\
            nbr.hexloc[2]-unit.hexloc[2])]
        print dirs[0]
        diri = HEXDIRECTIONS.index(dirs[0])
        dirs.append( HEXDIRECTIONS[(diri + 1)%6])
        dirs.append(HEXDIRECTIONS[diri-1 if diri-1>=0 else 5])

        searchList = []
        searchList.extend(self.p0units)
        searchList.extend(self.p1units)

        
        retList = []


        for dir in dirs:
            newLoc = [nbr.hexloc[0]+dir[0],nbr.hexloc[1]+dir[1],nbr.hexloc[2]+dir[2]]


            empty = True
            if not self.checkUnitListForLoc(searchList,newLoc) == None:
                empty = False
            #    print self.checkUnitListForLoc(searchList,newLoc).hexloc
            if not self.checkLocListForLoc(self.boardElements["border"][0],newLoc) == None:
                empty = False
                #print self.checkLocListForLoc(self.boardElements["border"][0],newLoc)

            if empty:
                retList.append(newLoc)
        return retList

    def isOnWarp(self,unit):
        return self.checkLocListForLoc(self.warps,unit.hexloc)

    #precondition, warploc is a real warp loc, in tuple form if this breaks ill fix
    def getNbrWarps(self,warpLoc):
        nbrs = []
        warpLoc = (warpLoc[0],warpLoc[1],warpLoc[2])
        if warpLoc in self.warps:
            i = self.warps.index(warpLoc)
            nbrs.append(self.warps[(i+1)%len(self.warps)])
            nbrs.append(self.warps[(i-1) if i-1>=0 else len(self.warps)-1])
        return nbrs

    def getAvailableNbrWarps(self,unit):
        retList = []
        if self.isOnWarp(unit):
            for loc in self.getNbrWarps(unit.hexloc):
                if self.isBoardLocEmpty(loc):
                    retList.append(loc)
        return retList

    def getPushableNbrs (self,unit):
        retList = []
        #print self.getNbrs(unit)
        for nbr in self.getNbrs(unit):

            pushSpace = self.getPushableSpaces(unit,nbr)
            if pushSpace == []:
                continue
            retList.append(nbr)
        return retList


    def locsInAllDirs(self,loc):
        retList = []
        for diri in range(6):
            dir = HEXDIRECTIONS[diri]
            retList.append([loc[0]+dir[0],loc[1]+dir[1],loc[2]+dir[2]])
        return retList
    def throwTwoFarLocs(self,loc):
        retList = []
        for diri in range(6):
            dir = HEXDIRECTIONS[diri]
            retList.append([loc[0]+dir[0]*2,loc[1]+dir[1]*2,loc[2]+dir[2]*2])
        return retList

    #does not apply to king
    def getNbrs(self,unit):
        #print locEq((0,0,0),(0,0,0))
        #print unit.hexloc
        retList = []
        for loc in self.locsInAllDirs(unit.hexloc):
            searchList = []
            searchList.extend(self.p0units)
            searchList.extend(self.p1units)
            #searchList.append(self.p0king if unit.team == 0 else self.p1king)
            #searchList.append(self.p1king)
            checkObj = self.checkUnitListForLoc(searchList,loc)
            if not checkObj == None:
                retList.append(checkObj)
        return retList
        

    def getAvailableThrowLocations(self, unit):
        retList = []
        neighbors = self.getNbrs(unit)
        numAllies = 0
        for n in neighbors:
            if n.team == self.activePlayer:#unit.team:
                numAllies +=1
        if numAllies >= 3:
            close = self.locsInAllDirs(unit.hexloc)
            far = self.throwTwoFarLocs(unit.hexloc)
            blockList = self.p0units if self.activePlayer == 1 else self.p1units
            for i in range(6):
                #loc = close[i]
            #for loc in self.locsInAllDirs(unit.hexloc):
                if self.isBoardLocEmpty(close[i], unit.team):
                    retList.append(close[i])
                if not self.checkUnitListForLoc(blockList, close[i]):
                    if self.isBoardLocEmpty(far[i], unit.team):
                        retList.append(far[i])


        return retList
        #check if can be thrown

    # Checks if the hexloc is empty,
    #    if team flag is set, RETURNS TRUE ON ENEMY KING
    def isBoardLocEmpty(self, loc, team=-1):
        for unit in self.p0units:
            if locEq(loc, unit.hexloc):
                return False
        for unit in self.p1units:
            if locEq(loc, unit.hexloc):
                return False
        if locEq(loc, self.p0king.hexloc) and team==0:
            return False
        if locEq(loc, self.p1king.hexloc) and team==1:
            return False
        if not self.checkLocListForLoc(self.boardElements["border"][0],loc) == None:
            return False
        return True

    #returns a list of walkable locations
    def getAvailableWalkLocations(self,unit):
        #print locEq((0,0,0),(0,0,0))
        #print unit.hexloc
        retList = []
        
        for dirIndex in range(6):
            loc = unit.hexloc
            dir  = HEXDIRECTIONS[dirIndex]
            newLoc = [loc[0]+dir[0],loc[1]+dir[1],loc[2]+dir[2]]
            searchList = []
            searchList.extend(self.p0units)
            searchList.extend(self.p1units)
            searchList.append(self.p0king if unit.team == 0 else self.p1king)
            #searchList.append(self.p1king)

            if(self.isBoardLocEmpty(newLoc, unit.team)):
                retList.append(newLoc)
            """empty = True

            if not self.checkUnitListForLoc(searchList,newLoc) == None:
                empty = False
            #    print self.checkUnitListForLoc(searchList,newLoc).hexloc
            if not self.checkLocListForLoc(self.boardElements["border"][0],newLoc) == None:
                empty = False
                #print self.checkLocListForLoc(self.boardElements["border"][0],newLoc)

            if empty:
                retList.append(newLoc)"""

        return retList

    def checkLocListForLoc(self,list,loc):
        for element in list:
            if locEq(loc,element):
                return element
        return None

    def checkUnitListForLoc(self,list,loc):
        for unit in list:
            if locEq(loc,unit.hexloc):
                return unit
        return None
    def getFlowerOutGrid(self):
        origincoord = (0,0,0)
        coordList = [origincoord]
        self.flowerOutNewHexs(origincoord, coordList)
        print "FlowerOut Successful:"
        return coordList

    def flowerOutNewHexs(self,coord,list):
        extreme = BOARDSIZE
        for val in coord:
            if math.fabs(val)>extreme:
                return
        newcoords = []

        newcoords.append((coord[0]-1,coord[1],coord[2]+1))
        newcoords.append((coord[0],coord[1]-1,coord[2]+1))
        newcoords.append((coord[0]+1,coord[1]-1,coord[2]))
        newcoords.append((coord[0]-1,coord[1]+1,coord[2]))
        newcoords.append((coord[0],coord[1]+1,coord[2]-1))
        newcoords.append((coord[0]+1,coord[1],coord[2]-1))
        for nc in newcoords:
            if not nc in list:
                list.append(nc)
                self.flowerOutNewHexs(nc,list)


    def getFlowerDownGrid(self):
        origincoord = (0,0,0)
        coordList = [origincoord]
        self.flowerDownNewHexs(origincoord, coordList)
        print "FlowerDown Successful:"
        return coordList

    def flowerDownNewHexs(self,coord,list):
        extreme = BOARDSIZE
        for val in coord:
            if math.fabs(val)>extreme:
                return
        newcoords = []

        newcoords.append((coord[0]-1,coord[1],coord[2]+1))
        newcoords.append((coord[0],coord[1]-1,coord[2]+1))
        newcoords.append((coord[0]+1,coord[1]-1,coord[2]))

        for nc in newcoords:
            if not nc in list:
                list.append(nc)
                self.flowerDownNewHexs(nc,list)



    def drawHexGridBG(self,surf):
        for loc in self.gridLocs:
            self.drawHexFill(surf,BOARDCOLOR,getPosFromHexLoc(loc),False)
    #def getHex
    def drawHexGrid(self,surf):

        for loc in self.gridLocs:

            if math.fabs(loc[0])>BOARDSIZE or math.fabs(loc[1])>BOARDSIZE \
                                            or math.fabs(loc[2])>BOARDSIZE:
                self.drawHexBorder(surf,getPosFromHexLoc(loc),False)
            else:
                self.drawHexTop(surf,getPosFromHexLoc(loc),False)

        return

    def drawHexTop(self,surf,loc,topleft = True):
        l = HEXSIDELEN
        if topleft:
            pts = [(),(),(),()]
            pts[0] = loc
            pts[1] = (loc[0]+l,loc[1])
            pts[2] = (pts[1][0]+dx(l,math.radians(60.0)),pts[1][1]+dy(l,math.radians(60.0)))
            pts[3] = (pts[0][0]+dx(l,math.radians(120.0)),pts[0][1]+dy(l,math.radians(60.0)))

            for pt in pts:
                pt = (int(pt[0]),int(pt[1]))
            line(surf,(0,0,0),pts[0],pts[1],LINETHICK)
            line(surf,(0,0,0),pts[1],pts[2],LINETHICK)
            line(surf,(0,0,0),pts[0],pts[3],LINETHICK)
        else:

            topleftpt = (loc[0]+dx(l,math.radians(-120.0)),loc[1]+dy(l,math.radians(-120.0)))
            self.drawHexTop(surf, topleftpt, True)
        return
    def drawHexBorder(self,surf,loc,topleft = True):
        l = HEXSIDELEN
        if not topleft:
            topleftpt = (loc[0]+dx(l,math.radians(-120.0)),loc[1]+dy(l,math.radians(-120.0)))
            self.drawHexBorder(surf, topleftpt, True)
        else:
            pts = [(),(),(),(),(),()]
            pts[0] = loc
            pts[1] = (loc[0]+l,loc[1])
            pts[2] = (pts[1][0]+dx(l,math.radians(60.0)),pts[1][1]+dy(l,math.radians(60.0)))
            pts[3] = (pts[2][0]+dx(l,math.radians(120.0)),pts[2][1]+dy(l,math.radians(120.0)))
            pts[4] = (pts[3][0]-l,pts[3][1])
            pts[5] = (pts[0][0]+dx(l,math.radians(120.0)),pts[0][1]+dy(l,math.radians(60.0)))

            for pt in pts:
                pt = (int(pt[0]),int(pt[1]))
            for i in range(len(pts)):
                line(surf,(0,0,0),pts[i],pts[(i+1)%6],LINETHICK)
            #polygon(surf,color,pts)
    def drawDirPoly(self,surf,loc,dir):
        pt1 = getPosFromHexLoc(loc)
        loc2 = [loc[0]+dir[0],loc[1]+dir[1],loc[2]+dir[2]]
        pt2 = getPosFromHexLoc(loc2)
        line(surf,(255,0,0),pt1,pt2,2)
        return
    
    def drawHexFill(self,surf,color,loc,topleft = True):
        l = HEXSIDELEN
        if not topleft:
            topleftpt = (loc[0]+dx(l,math.radians(-120.0)),loc[1]+dy(l,math.radians(-120.0)))
            self.drawHexFill(surf,color, topleftpt, True)
        else:
            pts = [(),(),(),(),(),()]
            pts[0] = loc
            pts[1] = (loc[0]+l,loc[1])
            pts[2] = (pts[1][0]+dx(l,math.radians(60.0)),pts[1][1]+dy(l,math.radians(60.0)))
            pts[3] = (pts[2][0]+dx(l,math.radians(120.0)),pts[2][1]+dy(l,math.radians(120.0)))
            pts[4] = (pts[3][0]-l,pts[3][1])
            pts[5] = (pts[0][0]+dx(l,math.radians(120.0)),pts[0][1]+dy(l,math.radians(60.0)))
            bpts = []
            for pt in pts:
                pt = (int(pt[0]),int(pt[1]))
                bpts.insert(0,pt)
            polygon(surf,color,pts)


    def drawTransHexList(self,surf,col,list,alpha):
        drawSurf = pygame.surf.Surf(surf.get_rect())

        drawSurf.fill(255,0,255)
        drawSurf.set_colorkey((255,0,255))

        for loc in list:
            self.drawHexFill(drawSurf,col,self.getPosFromHexLoc(loc, True),False)
        drawSurf.set_alpha(alpha)
        surf.blit(drawSurf,)
            
    def tick(self):
        etime = self.clock.tick()
        for e in pygame.event.get():
            self._handle_event(e)
        self.updateAll(etime)
        self.drawAll(self.screen)

        return





    def updateAll(self,etime):
        if self.state == ACTIVE:
            delList = []
            for lerp in self.locLerps:
                lerp.update(etime)
                if lerp.finished:
                    delList.append(lerp)
            for lerp in delList:
                self.locLerps.remove(lerp)

            if self.locLerps == []:
                self.endMovePushAction()
                #self.switchActivePlayer()


        if self.discoFlag:
            self.discoUpdate(etime)

        return

    def switchActivePlayer(self):
        self.activePlayer = (self.activePlayer+1)%2
        self.actionHighlight = []
        self.walkSpaces = []
        self.warpSpaces = []
        self.pushSelection = None
        self.pushSpace = []
        self.selectedUnit = None
        self.movedUnits = []
        self.thrownUnit = None
        
        self.state = IDLE
        self.checkUnitsAgainstKings()
        self.checkUnitsAgainstDeathTraps()
        self.movedThisTurn = False
        self.kingMovedThisTurn = False
        self.warpedThisTurn = False

        self.moveDraw = False
        self.pushedThisTurn = False
        self.thrownThisTurn = False

        self.scanAll()

        self.selectMode = None

    def startMoveAction(self,unit,loc):
        self.actionHighlight = []
        self.walkSpaces = []
        self.pushSelection = None
        self.pushSpace = []

        print "MOVING UNIT ",unit
        self.state = ACTIVE
        self.movedThisTurn = True
        self.moveDraw = True
        #self.moveToken = False

        self.movedUnits = [unit]

        self.locLerps.append(LocLerper(unit,loc,UNIT_MOVE_TIME))
        return


    def startKingMoveAction(self,unit,loc):
        self.actionHighlight = []
        self.walkSpaces = []
        self.pushSelection = None
        self.pushSpace = []

        print "MOVING UNIT ",unit
        self.state = ACTIVE
        self.movedThisTurn = True
        #self.thrownThisTurn = True
        self.moveDraw = True
        self.kingMovedThisTurn = True
        #self.moveToken = False

        self.movedUnits = [unit]

        self.locLerps.append(LocLerper(unit,loc,UNIT_MOVE_TIME))
        return


    def startWarpAction(self,unit,loc):
        self.actionHighlight = []
        self.walkSpaces = []
        self.pushSelection = None
        self.pushSpace = []

        print "MOVING UNIT ",unit
        self.state = ACTIVE
        self.movedThisTurn = True
        self.warpedThisTurn = True
        #self.thrownThisTurn = True
        self.moveDraw = True
        #self.moveToken = False

        self.movedUnits = [unit]

        self.locLerps.append(LocLerper(unit,loc,UNIT_MOVE_TIME))
        return
        #do much more stuff, set up interpolates
    def startPushAction(self,unit,pushUnit,loc):
        self.actionHighlight = []
        self.walkSpaces = []
        self.pushSelection = None
        self.pushSpace = []
        self.selectMode = None

        print "PUSHING UNITs ",unit, pushUnit
        self.state = ACTIVE
        self.movedThisTurn = True
        self.pushedThisTurn = True
        self.movedUnits = [unit,pushUnit]
        #self.moveToken = False

        self.locLerps.append(LocLerper(unit,pushUnit.hexloc,UNIT_MOVE_TIME))
        self.locLerps.append(LocLerper(pushUnit,loc,UNIT_MOVE_TIME))
        return
    def startThrowAction(self,unit,loc):
        self.actionHighlight = []
        self.walkSpaces = []
        self.throwSpaces = []
        self.pushSelection = None
        self.pushSpace = []

        self.movedThisTurn = True
        self.thrownThisTurn = True
        self.thrownUnit = unit
        self.movedUnits = []

        #self.moveToken = False
        print "MOVING UNIT ",unit
        self.state = ACTIVE
        self.movedThisTurn = True

        self.locLerps.append(LocLerper(unit,loc,UNIT_MOVE_TIME))
        return
    
    def endMovePushAction(self):
        self.actionHighlight = []
        self.walkSpaces = []
        self.pushSelection = None
        self.pushSpace = []
        self.pushableNbrs = []
        self.warpableUnits = []
        self.throwSpaces = []
        self.warpSpaces =  []
        self.selectedUnit = None
        self.state = IDLE
        self.checkUnitsAgainstKings()
        self.selectMode = None

        self.scanAll()
        if self.throwableUnits == [] and self.warpableUnits == [] or self.kingMovedThisTurn:
            self.switchActivePlayer()

            
        
    def locsInAllDirs(self,loc):
        retList = []
        for diri in range(6):
            dir = HEXDIRECTIONS[diri]
            retList.append([loc[0]+dir[0],loc[1]+dir[1],loc[2]+dir[2]])

        return retList
    def checkMouseRight(self,pos):
        self.mouseRemoveLoc(pos)

        self.selectedUnit = None
        self.pushSelection = None
        self.selectMode = None
        self.walkSpaces = []
        self.throwSpaces = []

        self.actionHighlight = []
        

        return

    def scanThrowableUnits(self):
        searchList = []
        self.throwableUnits = []

        if self.warpedThisTurn: #CHANGE THIS IF WANT TO INCORPORATE WARPING INTO JUMPING
            return
        
        if not self.movedThisTurn:
            searchList.extend(self.p0units)
            searchList.extend(self.p1units)


        if self.movedThisTurn:
            for u in self.movedUnits:
                searchList.extend(self.getNbrs(u))
                searchList.append(u)

        if self.thrownThisTurn:
            searchList.append(self.thrownUnit)



        for u in searchList:
            throwSpots = self.getAvailableThrowLocations(u)
            if not throwSpots == []:
                self.throwableUnits.append(u)


    def scanWarpableUnits(self):
        if self.warpedThisTurn:
            return
        searchList = []
        if not self.thrownThisTurn:
            searchList.extend(self.p0units if self.activePlayer == 0 else self.p1units)
        if self.movedThisTurn:
            searchList = self.movedUnits

        self.warpableUnits = []
        for u in searchList:
            if self.checkLocListForLoc(self.boardElements["warp"][0], u.hexloc):
                self.warpableUnits.append(u)




    def scanWalkableSpaces(self):
        if not self.selectedUnit == None and not self.movedThisTurn:
            self.walkSpaces = self.getAvailableWalkLocations(self.selectedUnit)

        else:
            self.walkSpaces == None

    def scanPushableUnits(self):
        if not self.selectedUnit == None and not self.movedThisTurn:
            self.pushableNbrs = self.getPushableNbrs(self.selectedUnit)
        else:
            self.pushableNbrs = []

    def scanAll(self):
        self.scanWalkableSpaces()
        self.scanPushableUnits()
        self.scanThrowableUnits()
        self.scanWarpableUnits()

        
    def checkMouseLeft(self,pos):
        #self.mouseAddLoc(pos)#checks for shift pressed
        #if self.selectedUnit == None:

        self.scanAll()

        if self.selectMode == KING_SELECT:
            if not self.selectedUnit == None:
                loc = self.mouseHexLoc(pos)
                checkVal =  self.checkLocListForLoc(self.walkSpaces,loc)
                if not checkVal == None:
                    self.startKingMoveAction(self.selectedUnit,checkVal)
                    return

            unitCheck = self.checkUnitClick(pos)
            if unitCheck == None:
                return

            else:# unitCheck == self.selectedUnit:
                self.selectMode = None
                self.walkSpaces = []
                self.selectedUnit = None

            
        
        if self.selectMode == None:

            if not self.movedThisTurn:
                kingCheck = self.checkKingClick(pos)
                if not kingCheck == None:
                    self.selectedUnit = kingCheck
                    self.selectMode = KING_SELECT
                    self.walkSpaces = self.getAvailableWalkLocations(self.selectedUnit)
                    self.actionHighlight = self.walkSpaces




            unitCheck = self.checkUnitClick(pos,True)
            if unitCheck == None:
                return
            self.selectedUnit = unitCheck




            
            if self.selectedUnit in self.throwableUnits:
                print "THROWABLE"
                self.throwSpaces = self.getAvailableThrowLocations(self.selectedUnit)

            elif not self.selectedUnit.team == self.activePlayer:
                self.selectedUnit = None
                return

            if self.selectedUnit in self.warpableUnits:
                self.warpSpaces = self.getAvailableNbrWarps(self.selectedUnit)
            self.scanAll()
            self.actionHighlight = []
            self.actionHighlight.extend(self.walkSpaces)#this is so other times of
            self.actionHighlight.extend(self.throwSpaces)
            self.actionHighlight.extend(self.warpSpaces)
            self.selectMode = SINGLE_SELECT

            self.pushSelection = None
            self.pushSpace = []
            #for element in self.pushableNbrs:
            #    self.actionHighlight.extend(element[1])
            #actions will be hihglighted later too

            return

        if self.selectMode == SINGLE_SELECT:
            if not self.selectedUnit == None:
                loc = self.mouseHexLoc(pos)
                checkVal =  self.checkLocListForLoc(self.walkSpaces,loc)
                if not checkVal == None:
                    self.startMoveAction(self.selectedUnit,checkVal)
                    return
                checkVal =  self.checkLocListForLoc(self.throwSpaces,loc)
                if not checkVal == None:
                    self.startThrowAction(self.selectedUnit,checkVal)
                    return
                checkVal = self.checkLocListForLoc(self.warpSpaces,loc)
                if not checkVal ==None:
                    self.startWarpAction(self.selectedUnit,checkVal)
                    return

            unitCheck = self.checkUnitClick(pos,True)
            if unitCheck == self.selectedUnit:
                self.selectedUnit = None
                self.pushSelection = None
                self.pushSpace = []
                self.walkSpaces = []
                self.warpSpaces = []
                self.actionHighlight = []
                self.throwSpaces = []
                self.selectMode = None
                return

            for unit in self.pushableNbrs:
                #print e
                if unit == unitCheck: #SELECT SOMEGUY FOR PUSHING
                    print "got ",unit
                    self.pushSelection = unitCheck
                    self.pushSpace = self.getPushableSpaces(self.selectedUnit, self.pushSelection)
                    self.actionHighlight = []
                    self.actionHighlight.extend(self.pushSpace)
                    self.walkSpaces = []
                    self.warpSpaces = []
                    self.selectMode = PUSH_SELECT
                    return
            
            unitCheck = self.checkUnitClick(pos)
            
            if unitCheck and not unitCheck == self.selectedUnit:
                self.selectedUnit = unitCheck
                if not self.movedThisTurn:
                    self.walkSpaces = self.getAvailableWalkLocations(self.selectedUnit)
                    self.getPushableNbrs(self.selectedUnit)
                self.actionHighlight = []
                if unitCheck in self.throwableUnits:
                    self.throwSpaces = self.getAvailableThrowLocations(self.selectedUnit)
                    self.actionHighlight.extend(self.throwSpaces)
                
                self.actionHighlight.extend(self.walkSpaces)#this is so other times of
                
                self.selectMode = SINGLE_SELECT
                self.pushSelection = None
                self.pushSpace = []



        if self.selectMode == PUSH_SELECT:
            if not self.pushSelection == None:
                loc = self.mouseHexLoc(pos)
                checkVal =  self.checkLocListForLoc(self.pushSpace,loc)
                if not checkVal == None:
                    #self.startMoveAction(self.selectedUnit,checkVal)
                    self.startPushAction(self.selectedUnit,self.pushSelection,checkVal)
                    #self.movedThisTurn = True
                    return
            unitCheck = self.checkUnitClick(pos,True)

            if unitCheck == self.pushSelection or unitCheck == self.selectedUnit:
                self.pushSelection = None
                self.pushSpace = []

                self.walkSpaces = self.getAvailableWalkLocations(self.selectedUnit)
                self.getPushableNbrs(self.selectedUnit)
                self.actionHighlight = []
                self.actionHighlight.extend(self.walkSpaces)#this is so other times of
                self.selectMode = SINGLE_SELECT


            
    #will assign winner
    def checkUnitsAgainstKings(self):
        #for u in self.p0units:
        if self.checkUnitListForLoc(self.p0units, self.p1king.hexloc):
            self.winner = 0
            self.state = GAMEOVER
            self.scores[0]+=1
        if self.checkUnitListForLoc(self.p1units,self.p0king.hexloc):
            self.winner = 1
            self.state = GAMEOVER
            self.scores[1]+=1

    def checkUnitsAgainstDeathTraps(self):
        searchList = []
        searchList.extend(self.p0units)
        searchList.extend(self.p1units)

        for loc in self.boardElements["death"][0]:
            #locs = element[0]

            checkVal = self.checkUnitListForLoc(searchList, loc)
            if not checkVal == None:
                checkVal.dead = True
                checkVal.hexloc = (-100,-100,-100)
                print "unit killed ",checkVal

    def mouseHexLoc(self,pos):
        buttonRad = HEXSIDELEN

        for loc in self.gridLocs:
            pt2 = getPosFromHexLoc(loc, False)
            if dist(pos,pt2)<buttonRad:
                print "clicked on loc (",loc,")"
                return loc

    def mouseAddLoc(self,pos):
        buttonRad = HEXSIDELEN
        if self.keyPressDict["SHIFT"]:
            for loc in self.gridLocs:
                pt2 = getPosFromHexLoc(loc, False)
                if dist(pos,pt2)<buttonRad:
                    print "clicked on loc (",loc,")"
                    if not loc in self.zoneList:
                        self.zoneList.append(loc)
                    return loc
    def mouseRemoveLoc(self,pos):
        buttonRad = HEXSIDELEN
        if self.keyPressDict["SHIFT"]:
            for loc in self.gridLocs:
                pt2 = getPosFromHexLoc(loc, False)
                if dist(pos,pt2)<buttonRad:
                    print "clicked on loc (",loc,")"
                    if loc in self.zoneList:
                        self.zoneList.remove(loc)
                    return loc
                
    def drawAll(self,surf):

        #surf.fill((255,255,255))
        surf.blit(self.bg,(0,0))
        #pygame.display.flip()
        
        #self.drawHexGridBG(surf)
        """if self.drawBoardElements:
            for element in self.boardElements.values():
                
                for hexloc in element[0]:
                    
                    self.drawHexFill(surf,element[1], getPosFromHexLoc(hexloc,True), False)"""

        if not self.actionHighlight == []:
            actCol = P0_AVAILABLE_MOVE_SPACE_COL if self.activePlayer == 0 else P1_AVAILABLE_MOVE_SPACE_COL
            for loc in self.actionHighlight:
                self.drawHexFill(surf,actCol,getPosFromHexLoc(loc,True),False)
        if not self.throwableUnits == []:
            col = (250,250,100)
            actCol = col#P0_AVAILABLE_MOVE_SPACE_COL if self.activePlayer == 0 else P1_AVAILABLE_MOVE_SPACE_COL
            #for unit in self.throwableUnits:
            #    self.drawHexFill(surf,actCol,getPosFromHexLoc(unit.hexloc,True),False)
        if self.discoFlag:
            for hexloc in self.animGridList:
                self.drawHexFill(surf, hexloc[1], getPosFromHexLoc(hexloc[0],True), False)
        for hexloc in self.zoneList:
                self.drawHexFill(surf,(200,200,200), getPosFromHexLoc(hexloc,True), False)
        if DEBUGCIRCLELOCS:
            for hexloc in self.gridLocs:
               circle(surf,(255,0,0),getPosFromHexLoc(hexloc,True),2)



        self.drawHexGrid(surf)

        #surf.blit(self.pushRens[self.activePlayer],(0,0))

        if self.moveDraw:
            ren = self.pushRens[self.activePlayer] if not self.moveDraw else self.moveRens[self.activePlayer]
            loc = ((70,200) if self.activePlayer == 0 else (720,200))
            surf.blit(ren,ren.get_rect(center = loc).topleft)
        elif self.pushedThisTurn:
            ren = self.pushRens[self.activePlayer]
            loc = ((70,200) if self.activePlayer == 0 else (720,200))
            surf.blit(ren,ren.get_rect(center = loc).topleft)

        if self.thrownThisTurn:
            loc = (80,260) if self.activePlayer == 0 else (730,260)
            surf.blit(self.throwRens[self.activePlayer],\
                self.throwRens[self.activePlayer].get_rect(center = loc).topleft)

        if self.warpedThisTurn:
            loc = (80,260) if self.activePlayer == 0 else (730,260)
            surf.blit(self.warpRens[self.activePlayer],\
                self.warpRens[self.activePlayer].get_rect(center = loc).topleft)

        p0dloc = [50,500]
        p1dloc = [750,500]
        shift = 10
        numDead = [0,0]
        for i in range(8):
            if not self.p0units[i].dead:
                self.p0units[i].draw(surf)
            else:
                self.p0units[i].drawDead(surf,(p0dloc[0]+numDead[0]*shift,p0dloc[1]))
                numDead[0]+=1


            if not self.p1units[i].dead:
                self.p1units[i].draw(surf)
            else:
                self.p1units[i].drawDead(surf,(p1dloc[0]-numDead[1]*shift,p0dloc[1]))
                numDead[0]+=1

        if self.state == IDLE and not self.selectedUnit == None:
            col = P0UNITSELECTCOLOR if self.selectedUnit.team == 0 else P1UNITSELECTCOLOR
            ringcol = (255,0,0) if self.selectedUnit.team == 0 else (0,0,255)
            circle(surf,col,getPosFromHexLoc(self.selectedUnit.hexloc,True),12)
            circle(surf,ringcol,getPosFromHexLoc(self.selectedUnit.hexloc,True),17,2)
        if self.state == IDLE and not self.pushSelection == None:
            col = P0UNITSELECTCOLOR if self.selectedUnit.team == 0 else P1UNITSELECTCOLOR
            ringcol = (255,0,0) if self.pushSelection.team == 0 else (0,0,255)
            circle(surf,col,getPosFromHexLoc(self.pushSelection.hexloc,True),12)
            circle(surf,ringcol,getPosFromHexLoc(self.pushSelection.hexloc,True),25,1)

        self.p0king.draw(surf)
        self.p1king.draw(surf)
        for i in range(self.scores[0]):
            loc = [32+i*32,100]
            surf.blit(self.crown,self.crown.get_rect(center=loc).topleft)
        for i in range(self.scores[1]):
            loc = [768-(i*32),100]
            surf.blit(self.crown,self.crown.get_rect(center=loc).topleft)
        if self.state == GAMEOVER:
            drawsurf = self.p1WinRen if self.winner == 0 else self.p2WinRen
            surf.blit(drawsurf,drawsurf.get_rect(center = (400,300)).topleft)

        else:
            if self.activePlayer ==0:
                ren = self.turnFont.render("PLAYER 1's TURN",1,(255,0,0))
            else:
                ren = self.turnFont.render("PLAYER 2's TURN",1,(0,0,255))
            surf.blit(ren,ren.get_rect(center = (400,540)).topleft)

        pygame.display.flip()

    def saveZone(self):
        if self.zoneList == []:
            print "No Zone to save!"
            return
        name = ask(self.screen,"Save Zone As?")

        if name == "" or name == "x":
            return
        saveFile = open("../zones/"+name+".pkl",'wb')
        pickle.dump(self.zoneList,saveFile)

    def loadZone(self,name):
        if name == "" or name == "x":
            return
        loadFile = open("../zones/"+name+".pkl",'rb')
        return pickle.load(loadFile)

    def _handle_event(self,event):
        #super._handle_event(self,event)
        if event.type == pygame.QUIT:
            pygame.quit()
            #raise EndOfGameException("Quit")
            exit(0)

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                exit(0)
            if event.key == pygame.K_r or event.key == pygame.K_F3:
                self.setup()
        if self.state == GAMEOVER:
            return

        if event.type == pygame.KEYDOWN:
                #raise EndOfGameException("Quit")
            if event.key == pygame.K_d:
                self.discoFlag = not self.discoFlag
            if event.key == pygame.K_p:
                self.scanThrowableUnits()
                self.scanWarpableUnits()
                print "ThrowableUnits", self.throwableUnits
                print "WarpableUnits",self.warpableUnits
            if event.key == pygame.K_RETURN:
                self.executeJumps()
            if event.key == pygame.K_LSHIFT:
                self.keyPressDict['SHIFT'] = True
            if event.key == pygame.K_DOWN:
                self.keyPressDict['DOWN'] = True

            if event.key == pygame.K_UP:
                self.movePlayer()
                self.keyPressDict['UP'] = True
            if event.key == pygame.K_LEFT:
                self.turnPlayer(1)
                self.movePlayer()
                self.keyPressDict['LEFT'] = True
            if event.key == pygame.K_SPACE:
                self.switchActivePlayer()
                return
            if event.key == pygame.K_RIGHT:
                self.turnPlayer(-1)
                self.movePlayer()
                self.keyPressDict['RIGHT'] = True
            if event.key == pygame.K_s:
                self.keyPressDict['DOWN'] = True
            if event.key == pygame.K_w:
                self.keyPressDict['UP'] = True
            if event.key == pygame.K_a:
                self.keyPressDict['LEFT'] = True
            if event.key == pygame.K_d:
                self.keyPressDict['RIGHT'] = True
            if event.key == pygame.K_j:
                self.testCalcJumpDisp()
            if event.key == pygame.K_F5:
                self.saveZone()
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_DOWN:
                self.keyPressDict['DOWN'] =False
            if event.key == pygame.K_UP:
                self.keyPressDict['UP'] = False
            if event.key == pygame.K_LEFT:
                self.keyPressDict['LEFT'] = False
            if event.key == pygame.K_RIGHT:
                self.keyPressDict['RIGHT'] =False
            if event.key == pygame.K_s:
                self.keyPressDict['DOWN'] = False
            if event.key == pygame.K_w:
                self.keyPressDict['UP'] = False
            if event.key == pygame.K_a:
                self.keyPressDict['LEFT'] = False
            if event.key == pygame.K_d:
                self.keyPressDict['RIGHT'] = False
            if event.key == pygame.K_LSHIFT:
                self.keyPressDict['SHIFT'] = False

        if event.type== pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                self.mouseHold = True
                self.checkMouseLeft(pygame.mouse.get_pos())
                #loc = getGridLocFromMouse(pygame.mouse.get_pos())
            if event.button == 3:
                self.checkMouseRight(pygame.mouse.get_pos())
                
        if event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                self.mouseHold = False

        if event.type == pygame.MOUSEMOTION:
            if self.mouseHold:
                #self.checkMouseLeft(pygame.mouse.get_pos())
                return
            pass

    def discoUpdate(self,etime):
        self.gridanimtick+=etime
        if self.gridanimtick>self.animspd:
            self.animGridList = random.sample(self.gridLocs,random.randrange(20,70))
            for i in range(len(self.animGridList)):
                self.animGridList[i]=(self.animGridList[i],(random.choice(RAINBOW2)))
            self.gridanimtick = 0.0
            self.animspd +=random.randrange(-5,10)
            if self.animspd<25 or self.animspd>175:
                self.animspd = 100
if __name__ == "__main__":

    engine = HexWorld()
    print "welcome,sit down and stay for a while(True)"
    while(True):
        engine.tick()



